package com.xbx.admin.service.user.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.xbx.common.constant.ResultConstant;
import com.xbx.common.utils.EntityUtils;
import com.xbx.common.utils.MyUtils;
import com.xbx.common.utils.ObjectUtils;
import com.xbx.admin.cache.ShiroCleanBean;
import com.xbx.admin.constant.UserManagerConstant;
import com.xbx.admin.dataobject.*;
import com.xbx.admin.entity.user.*;
import com.xbx.admin.entity.user.form.RoleInfoForm;
import com.xbx.admin.entity.user.form.SettingModuleForm;
import com.xbx.admin.entity.user.form.UserInfoForm;
import com.xbx.admin.entity.user.req.UserInfoReq;
import com.xbx.admin.entity.user.res.AreaChildVo;
import com.xbx.admin.entity.user.res.AreaParentVo;
import com.xbx.admin.entity.user.res.AreaTopVo;
import com.xbx.admin.mapper.*;
import com.xbx.admin.service.user.UserService;
import com.xbx.admin.utils.UserUtlis;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 用户管理实现类
 *
 * @author 89005691
 * @create 2018-08-30 20:06
 */
@Service
@Slf4j
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDOMapper userDOMapper;

    @Autowired
    private UserRoleDOMapper userRoleDOMapper;

    @Autowired
    private RoleDOMapper roleDOMapper;

    @Autowired
    private ModuleDOMapper moduleDOMapper;

    @Autowired
    private RoleModuleDOMapper roleModuleDOMapper;

    @Autowired
    private ShiroCleanBean shiroCleanBean;

    @Autowired
    private DictionaryDOMapper dictionaryDOMapper;

    @Override
    public PageInfo<User> pageUserInfoList(UserInfoReq userInfoReq) {

        Map<String, Object> map = new HashMap<>();

        map.put("status", true);

        if(userInfoReq.getRoleId() != null){

            map.put("queryRoleId", userInfoReq.getRoleId());
        }

        if(StringUtils.isNotEmpty(userInfoReq.getUsername())){

            map.put("queryUsername", "%" + userInfoReq.getUsername() + "%");
        }

        if(StringUtils.isNotEmpty(userInfoReq.getSysUsername())){

            map.put("querySysUsername", "%" + userInfoReq.getSysUsername() + "%");
        }

        Page<User> page = PageHelper.startPage(userInfoReq.getCurrentPage(), userInfoReq.getPageSize());

        userDOMapper.selectByMapAndRoleName(map);

        PageInfo<User> pageInfo = new PageInfo<>(page);

        pageInfo.setList(EntityUtils.transform(pageInfo.getList(), User.class));

        return pageInfo;
    }

    /**
     * 用户授予角色
     */
    public String allocateRole(UserInfoForm userInfoForm) throws Exception {

        // 查询旧记录
        UserDO userDO = userDOMapper.selectByPrimaryKey(userInfoForm.getId());

        if (userDO == null) {

            return "不存在用户记录";
        }

        // 修改角色用户对应关系信息
        this.updateRole(userInfoForm);

        return ResultConstant.OPREATE_SUCCESS;
    }

    /**
     * 修改角色信息
     */
    private void updateRole(UserInfoForm userInfoForm) {

        // 删除上一次的角色信息
        UserRoleDOExample example = new UserRoleDOExample();
        UserRoleDOExample.Criteria criteria = example.createCriteria();

        criteria.andUserIdEqualTo(userInfoForm.getId());

        this.userRoleDOMapper.deleteByExample(example);

        if(StringUtils.isNotEmpty(userInfoForm.getRoleId())){

            List<Long> roles = MyUtils.generateByLongArrays(userInfoForm.getRoleId(), ",");

            for (Long roleId : roles) {

                UserRoleDO userRoleDO = new UserRoleDO();

                userRoleDO.setUserId(userInfoForm.getId());
                userRoleDO.setRoleId(roleId);
                userRoleDO.setModifyTm(MyUtils.generateTime());
                // 获取用户信息
                com.xbx.baseweb.model.User user = UserUtlis.getLoginUserInfo();

                userRoleDO.setModifierUser(user.getUsername());

                this.userRoleDOMapper.insert(userRoleDO);
            }
        }
    }

    /**
     * 删除用户
     */
    @Override
    public String deleteUser(Long id) throws Exception {

        UserDO userDO = this.userDOMapper.selectByPrimaryKey(id);

        if (userDO == null) {

            return "不存在用户记录";
        }

        // 获取用户信息
        com.xbx.baseweb.model.User user = UserUtlis.getLoginUserInfo();

        userDO.setModifierUser(user.getUsername());
        userDO.setModifyTm(MyUtils.generateTime());
        userDO.setStatus(false);

        this.userDOMapper.updateByPrimaryKeySelective(userDO);

        return ResultConstant.OPREATE_SUCCESS;
    }

    @Override
    public PageInfo<Role> pageRoleInfoList(UserInfoReq userInfoReq) {

        RoleDOExample roleDOExample = new RoleDOExample();

        RoleDOExample.Criteria criteria = roleDOExample.createCriteria();

        criteria.andStatusGreaterThan(UserManagerConstant.ROLE_STATUS_INVALID);

        Page<Role> page = PageHelper.startPage(userInfoReq.getCurrentPage(), userInfoReq.getPageSize());

        roleDOMapper.selectByExample(roleDOExample);

        PageInfo<Role> pageInfo = new PageInfo<>(page);

        pageInfo.setList(EntityUtils.transform(pageInfo.getList(), Role.class));

        return pageInfo;
    }

    /**
     * 改变角色状态
     */
    public String changeRole(Long id, Integer status) throws Exception {

        // 查询角色信息
        RoleDOExample roleDOExample = new RoleDOExample();

        RoleDOExample.Criteria criteria = roleDOExample.createCriteria();

        criteria.andStatusGreaterThan(UserManagerConstant.ROLE_STATUS_INVALID);
        criteria.andRoleIdEqualTo(id);

        List<RoleDO> roleDOs = this.roleDOMapper.selectByExample(roleDOExample);

        if (ObjectUtils.isNull(roleDOs)) {

            return "角色不存在";
        }

        RoleDO roleDO = roleDOs.get(0);

        if (UserManagerConstant.ROLE_STATUS_ENABLED == roleDO.getStatus() && status == UserManagerConstant.ROLE_STATUS_ENABLED) {

            return "请勿重复启用";
        }

        if (UserManagerConstant.ROLE_STATUS_DISABLED == roleDO.getStatus() && status == UserManagerConstant.ROLE_STATUS_DISABLED) {

            return "请勿重复禁用";
        }

        RoleDO update = new RoleDO();

        // 获取用户信息
        com.xbx.baseweb.model.User user = UserUtlis.getLoginUserInfo();

        update.setRoleId(roleDO.getRoleId());
        update.setModifierUser(user.getUsername());
        update.setModifyTm(MyUtils.generateTime());
        update.setStatus(status);

        this.roleDOMapper.updateByPrimaryKeySelective(update);

        shiroCleanBean.updatePermission();

        return ResultConstant.OPREATE_SUCCESS;
    }

    /**
     * 创建用户角色
     */
    public String createRole(RoleInfoForm roleInfoForm) throws Exception {

        // 判断角色是否已经存在
        RoleDOExample roleDOExample = new RoleDOExample();
        RoleDOExample.Criteria criteria = roleDOExample.createCriteria();

        criteria.andRoleNameEqualTo(roleInfoForm.getRoleName());
        criteria.andStatusNotEqualTo(UserManagerConstant.ROLE_STATUS_INVALID);

        int count = this.roleDOMapper.countByExample(roleDOExample);

        if (count > 0) {

            return "角色名称已存在";
        }

        // 获取用户信息
        com.xbx.baseweb.model.User user = UserUtlis.getLoginUserInfo();

        RoleDO roleDO = new RoleDO();

        roleDO.setRoleCode(this.generateRoleCode());

        roleDO.setRoleName(roleInfoForm.getRoleName());
        roleDO.setRoleDesc(roleInfoForm.getRoleDesc());
        roleDO.setStatus(UserManagerConstant.ROLE_STATUS_ENABLED);
        roleDO.setCreatorUser(user.getUsername());
        roleDO.setCreateTm(MyUtils.generateTime());

        this.roleDOMapper.insert(roleDO);

        return ResultConstant.OPREATE_SUCCESS;
    }

    /**
     * 生成角色code
     *
     * @return
     */
    private String generateRoleCode() {

        String roleCode = MyUtils.generateCountRand(10);

        // 校验是否重复
        RoleDOExample roleDOExample = new RoleDOExample();
        RoleDOExample.Criteria criteria = roleDOExample.createCriteria();

        criteria.andRoleCodeEqualTo(roleCode);

        List<RoleDO> roleDOS = this.roleDOMapper.selectByExample(roleDOExample);

        if (ObjectUtils.isNotNull(roleDOS)) {

            return generateRoleCode();
        }

        return roleCode;
    }

    @Override
    public List<Module> listModuleInfoList(boolean selectButton, Long roleId) {

        List<Long> roleIds = null;

        // 查询当前角色所拥有的权限
        if (!selectButton) {

            roleIds = this.selectRoleIdByCurrentUser();
        } else {

            roleIds = new ArrayList<>();
            roleIds.add(roleId);
        }

        if (ObjectUtils.isNull(roleIds)) {

            return new ArrayList<>();
        }

        // 查询所有的菜单节点
        List<Module> rootList = this.selectRootList(roleIds, selectButton);

        if (ObjectUtils.isNotNull(rootList)) {

            // 查询菜单项和按钮
            this.selectItemList(rootList, selectButton, roleIds);
        }

        return rootList;
    }

    /**
     * 查询当前用户所分配的角色id
     */
    private List<Long> selectRoleIdByCurrentUser() {

        // 获取用户信息
        com.xbx.baseweb.model.User user = UserUtlis.getLoginUserInfo();

        List<UserDOAndRoleDO> userRoleDO = this.userRoleDOMapper.selectRoleIdByCurrentUser(user.getId());

        if (ObjectUtils.isNotNull(userRoleDO)) {

            List<Long> roleIds = new ArrayList<>();

            for (UserDOAndRoleDO userDOAndRoleDO : userRoleDO) {

                roleIds.add(userDOAndRoleDO.getRoleId());
            }

            return roleIds;
        }

        return new ArrayList<>();
    }

    /**
     * 查询所有的菜单节点
     */
    private List<Module> selectRootList(List<Long> roleIds, boolean selectButton) {

        Map<String, Object> map = new HashMap<>();

        map.put("moduleType", UserManagerConstant.MENU_TYPE_ROOT);
        map.put("roleId", roleIds);

        List<Module> modules = EntityUtils.transform(moduleDOMapper.selectRootList(map), Module.class);

        // 如果是不查询按钮则过滤没有权限的菜单
        if (!selectButton && ObjectUtils.isNotNull(modules)) {

            this.filterNotPermission(modules);
        }

        return modules;
    }

    /**
     * 如果是不查询按钮则过滤没有权限的菜单
     */
    private void filterNotPermission(List<Module> modules) {

        for (int i = modules.size() - 1; i >= 0; i--) {

            Module temp = modules.get(i);

            if (!temp.getChecked()) {

                modules.remove(i);
            }
        }
    }

    /**
     * 查询所有的菜单节点
     */
    private void selectItemList(List<Module> rootList, boolean selectButton, List<Long> roleIds) {

        this.selectModules(rootList, roleIds, selectButton);

        if (selectButton) {

            // 查询按钮
            this.selectModuleButtons(rootList, roleIds);
        }
    }

    private void selectModules(List<Module> rootList, List<Long> roleIds, boolean selectButton) {

        Map<String, Object> map = new HashMap<>();

        map.put("moduleType", UserManagerConstant.MENU_TYPE_ITEM);
        map.put("roleId", roleIds);

        List<ModuleDO> moduleDOS = moduleDOMapper.selectRootList(map);

        if (ObjectUtils.isNotNull(moduleDOS)) {

            for (Module module : rootList) {

                List<ModuleItem> items = new ArrayList<>();

                for (ModuleDO childItem : moduleDOS) {

                    if (childItem.getParentId().intValue() == module.getModuleId().intValue()) {

                        ModuleItem moduleItem = EntityUtils.transform(childItem, ModuleItem.class);

                        // 查询按钮或者是有权限
                        if (selectButton || moduleItem.getChecked()) {

                            items.add(moduleItem);
                        }
                    }

                    module.setItems(items);
                }
            }
        }
    }

    private void selectModuleButtons(List<Module> rootList, List<Long> roleIds) {

        Map<String, Object> map = new HashMap<>();

        map.put("moduleType", UserManagerConstant.MENU_TYPE_BUTTON);
        map.put("roleId", roleIds);

        List<ModuleDO> moduleDOS = moduleDOMapper.selectRootList(map);

        if (ObjectUtils.isNotNull(moduleDOS)) {

            for (Module module : rootList) {

                for(ModuleItem temp : module.getItems()){

                    List<ModuleButton> buttons = new ArrayList<>();

                    for (ModuleDO childItem : moduleDOS) {

                        if (childItem.getParentId().intValue() == temp.getModuleId().intValue()) {

                            ModuleButton moduleButton = EntityUtils.transform(childItem, ModuleButton.class);

                            buttons.add(moduleButton);
                        }

                        temp.setItems(buttons);
                    }
                }
            }
        }
    }

    /**
     * 设置权限
     */
    public String settingPermission(SettingModuleForm settingModuleForm) throws Exception {

        // 查询旧记录
        RoleDO roleDO = roleDOMapper.selectByPrimaryKey(settingModuleForm.getRoleId());

        if (roleDO == null) {

            return "不存在角色记录";
        }

        // 修改角色菜单对应关系信息
        this.updateModuleRole(settingModuleForm);

        shiroCleanBean.updatePermission();

        return ResultConstant.OPREATE_SUCCESS;
    }

    /**
     * 修改角色菜单对应关系信息
     */
    private void updateModuleRole(SettingModuleForm settingModuleForm) {

        // 删除上一次的角色信息
        RoleModuleDOExample example = new RoleModuleDOExample();
        RoleModuleDOExample.Criteria criteria = example.createCriteria();

        criteria.andRoleIdEqualTo(settingModuleForm.getRoleId());

        this.roleModuleDOMapper.deleteByExample(example);

        // 判断是否有设置菜单权限
        List<Long> moduleIds = MyUtils.generateByLongArrays(settingModuleForm.getModuleIds(), ",");

        for (Long id : moduleIds) {

            RoleModuleDO userRoleDO = new RoleModuleDO();

            userRoleDO.setRoleId(settingModuleForm.getRoleId());
            userRoleDO.setModuleId(id);
            userRoleDO.setModifyTm(MyUtils.generateTime());
            // 获取用户信息
            com.xbx.baseweb.model.User user = UserUtlis.getLoginUserInfo();

            userRoleDO.setModifierUser(user.getUsername());

            this.roleModuleDOMapper.insert(userRoleDO);
        }
    }

    /**
     * 删除角色
     */
    public String deleteRole(Long id) throws Exception {

        // 查询旧记录
        RoleDO roleDO = roleDOMapper.selectByPrimaryKey(id);

        if (roleDO == null) {

            return "不存在角色记录";
        }

        if (roleDO.getStatus() == UserManagerConstant.ROLE_STATUS_INVALID) {

            return "不存在角色记录";
        }

        RoleDO update = new RoleDO();

        // 获取用户信息
        com.xbx.baseweb.model.User user = UserUtlis.getLoginUserInfo();

        update.setRoleId(roleDO.getRoleId());
        update.setModifierUser(user.getUsername());
        update.setModifyTm(MyUtils.generateTime());
        update.setStatus(UserManagerConstant.ROLE_STATUS_INVALID);

        this.roleDOMapper.updateByPrimaryKeySelective(update);

        shiroCleanBean.updatePermission();

        return ResultConstant.OPREATE_SUCCESS;
    }

    /**
     * 根据modulecode拆分list
     */
    private List<AreaTopVo> generateAreaModel(List<Area> areas) {

        List<AreaTopVo> areaTopVos = new ArrayList<>();

        if (ObjectUtils.isNotNull(areas)) {

            // 顶级区index
            int topIndex = -1;

            // 大区index
            int regionIndex = -1;

            for (Area temp : areas) {

                // 是否取上一次的
                boolean hasOld = false;

                AreaTopVo areaTopVo = null;
                AreaParentVo insertParent = new AreaParentVo();
                // 大区list
                List<AreaParentVo> parentVos = null;
                // 地区list
                List<AreaChildVo> childVos = null;
                // 如果这次的顶级地区名称和上次一致则取上次的，下面的同理
                if (topIndex != -1 && areaTopVos.get(topIndex).getTopArea().equals(temp.getTopArea())) {

                    areaTopVo = areaTopVos.get(topIndex);
                    parentVos = areaTopVo.getAreaParentVos();

                    if (regionIndex != -1 && parentVos.get(regionIndex).getRegionArea().equals(temp.getRegionArea())) {

                        insertParent = parentVos.get(regionIndex);
                        childVos = insertParent.getAreaChildVos();
                        hasOld = true;
                    } else {

                        childVos = new ArrayList<>();

                        regionIndex++;
                    }
                } else {

                    // 重置regionIndex
                    regionIndex = -1;

                    areaTopVo = new AreaTopVo();
                    parentVos = new ArrayList<>();

                    childVos = new ArrayList<>();

                    areaTopVo.setTopArea(temp.getTopArea());
                    if (StringUtils.isEmpty(temp.getRegionArea()) && StringUtils.isEmpty(temp.getSubArea())) {

                        areaTopVo.setId(temp.getId());
                    }
                    areaTopVo.setChecked(temp.getChecked());
                }

                if (parentVos == null) {

                    parentVos = new ArrayList<>();
                }

                if (childVos == null) {

                    childVos = new ArrayList<>();
                }

                if (StringUtils.isEmpty(temp.getSubArea()) && StringUtils.isNotEmpty(temp.getRegionArea())) {

                    insertParent.setId(temp.getId());
                }

                insertParent.setRegionArea(temp.getRegionArea());
                insertParent.setChecked(temp.getChecked());

                if (StringUtils.isNotEmpty(temp.getSubArea())) {

                    AreaChildVo insertChild = new AreaChildVo();

                    insertChild.setId(temp.getId());
                    insertChild.setSubArea(temp.getSubArea());
                    insertChild.setChecked(temp.getChecked());

                    childVos.add(insertChild);

                    insertParent.setAreaChildVos(childVos);
                }

                if (!hasOld) {

                    parentVos.add(insertParent);
                }

                if (insertParent.getId() != null) {

                    areaTopVo.setAreaParentVos(parentVos);
                }

                if (topIndex == -1 || !areaTopVos.get(topIndex).getTopArea().equals(temp.getTopArea())) {

                    // 不包含则添加
                    areaTopVos.add(areaTopVo);
                    topIndex++;

                    if (!hasOld) {

                        regionIndex++;
                    }
                }
            }
        }

        return areaTopVos;
    }

    /**
     * 根据modulecode拆分list
     */
    private List<Area> splitAreaByModuleCode(List<Area> areas, String moduleCode){

        List<Area> result = new ArrayList<>();

        if (MyUtils.listIsNotNull(areas)) {

            for (Area area : areas) {

                if (moduleCode.equals(area.getBelongModuleCode())) {

                    result.add(area);
                }
            }
        }

        return result;
    }

    /**
     * 查询按钮是否有权限
     */
    public List<Module> selectAuthByCodes(String codes) {

        List<String> codeList = Arrays.asList(codes.split(","));

        // 获取当前用户的roleID
        List<Long> roleId = this.selectRoleIdByCurrentUser();

        Map<String, Object> map = new HashMap<>();

        map.put("moduleType", UserManagerConstant.MENU_TYPE_BUTTON);
        map.put("roleId", roleId);
        map.put("codes", codeList);

        return EntityUtils.transform(moduleDOMapper.selectRootList(map), Module.class);
    }

    /**
     * 修改角色信息
     */
    private void updateSingleRole(UserInfoForm userInfoForm) {

        UserRoleDOExample example = new UserRoleDOExample();
        UserRoleDOExample.Criteria criteria = example.createCriteria();

        criteria.andUserIdEqualTo(userInfoForm.getId());
        criteria.andRoleIdEqualTo(Long.valueOf(userInfoForm.getRoleId()));

        int count = this.userRoleDOMapper.countByExample(example);

        if (count == 0) {

            UserRoleDO userRoleDO = new UserRoleDO();

            userRoleDO.setUserId(userInfoForm.getId());
            userRoleDO.setRoleId(Long.valueOf(userInfoForm.getRoleId()));
            userRoleDO.setModifyTm(MyUtils.generateTime());
            // 获取用户信息
            com.xbx.baseweb.model.User user = UserUtlis.getLoginUserInfo();

            userRoleDO.setModifierUser(user.getUsername());

            this.userRoleDOMapper.insert(userRoleDO);
        }
    }
}
